import { Node } from "cc";
import { ecs } from "db://app-game/libs/ecs/ECS";
import { Rectangle } from "db://app-game/libs/math/auad-tree/Rectangle";
import Simulator from "db://app-game/libs/math/rov2/Simulator";
import { UIID } from "../../common/config/GameUIConfig";
import { CameraEnt } from "../../common/ecs/camera/Camera";
import {
  MonitorGroupComp,
  QueryParams,
} from "../../common/ecs/model/MonitorGroupComp";
import { Joysitick } from "../../ecs/joysitick/Joysitick";
import { MapE } from "../../ecs/map/Map";
import { Role } from "../../ecs/role/Role";
import { Load } from "../load/Load";
import { LevelBaseModelComp } from "./model/LevelBaseModelComp";
import { MonsterFactoryComp } from "./model/MonsterFactoryComp";
import { LevelViewComp } from "./view/LevelViewComp";

/** 关卡 */
@ecs.register("Level")
export class Level extends ecs.Entity {
  // 数据层
  /** 基础数据组件 */
  LevelBaseModel!: LevelBaseModelComp;
  /** 怪兽工厂组件 */
  MonsterFactory!: MonsterFactoryComp;

  // 业务层
  /* 监视组件 */
  MonitorGroup!: MonitorGroupComp;
  // 视图层
  /** 关卡视图组件 */
  LevelView!: LevelViewComp;

  // 子级实例层
  /** 摄像机实例 */
  camera!: CameraEnt;
  /** 模拟器实例 */
  simulator!: Simulator;
  /** 地图实例 */
  map!: MapE;
  /** 控制角色 */
  controlRole!: Role;

  /**UI层实例组 */
  UILayerEntityGroup: {
    /** 移动摇杆 */
    moveJoysitick: Joysitick;
    /** 射击摇杆 */
    shootJoysitick: Joysitick;
    /** 近战攻击摇杆 */
    closeCombatJoysitick: Joysitick;
  };

  init() {
    // 1.添加摄像机实例
    this.camera = ecs.getEntity<CameraEnt>(CameraEnt);
    this.addChild(this.camera);

    // 2.添加模拟器实例
    this.initSimulator();

    // 3.添加UI层实例
    this.UILayerEntityGroup = {
      moveJoysitick: null,
      shootJoysitick: null,
      closeCombatJoysitick: null,
    };

    // 2.添加关卡基础组件
    this.add(LevelBaseModelComp);
  }

  /** 初始化 */
  initSimulator() {
    this.simulator = new Simulator();
    let simulator = this.simulator;
    simulator.setTimeStep(0.5);
    simulator.setAgentDefaults(
      //在寻找周围邻居的搜索距离，这个值设置越大，会让小球在越远距离做出避障行为
      100, // neighbor distance (min = radius * radius)

      //寻找周围邻居的最大数目，这个值设置越大，最终计算的速度越 精确，但会加大计算量
      10, // max neighbors

      //计算动态的物体时的时间窗口
      100, // time horizon

      //代表计算静态的物体时的时间窗口，比如在RTS游戏中，小兵 向城墙移动时，没必要做出避障，这个值需要设置的很
      1, // time horizon obstacles

      //代表计算ORCA时的小球的半径，这个值不一定与小球实际显示的半径 一样，偏小有利于小球移动顺畅
      15, // agent radius

      //小球最大速度值
      2 // max speed
      //初始速度
      // 0, // default velocity for x
      // 0, // default velocity for y
    );
  }

  /** 跳转到游戏关卡 */
  goto() {
    const load = ecs.getEntity<Load>(Load);
    load.loadRes(
      UIID.Level,
      [
        { text: "正在加载游戏资源...", path: "prefab" },
        { text: "正在加载游戏资源...", path: "dragon-bones" },
        { text: "正在加载游戏资源...", path: "images/map/map1" },
        { text: "正在加载游戏资源...", path: "images/map/static-creature" },
        { text: "正在加载游戏资源...", path: "images/ui" },
        { text: "正在加载游戏资源...", path: "prefab/common" },
      ],
      this.jumpCompleted.bind(this)
    );
  }

  /** 加载跳转完成 */
  jumpCompleted(node: Node) {
    // 1.添加关卡视图组件
    this.add(node.getComponent(LevelViewComp)!);
    // 2.添加
  }

  /** 碰撞体列表 */
  colliderList(queryParams: QueryParams) {
    const { quadTreeObj } = this.map.MonitorGroup;
    const { name, circle } = queryParams;
    if (name && quadTreeObj[name]) {
      return quadTreeObj[name]?.retrieve(circle) || [];
    }
    return [];
  }

  /** 获取最近碰撞体 */
  recentlyCollider(queryParams: QueryParams) {
    const { quadTreeObj } = this.map.MonitorGroup;
    const { name, circle } = queryParams;
    if (name && quadTreeObj[name]) {
      return quadTreeObj[name].retrieveRange(circle) as unknown as Rectangle<{
        node: Node;
      }>;
    }
    return null;
  }
}
